﻿using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Collections.Generic;
using System.Configuration;
using System.Text;
using System.Windows.Forms;
using Goway.Log4net;

namespace Goway.StackingUC.Modules
{
    /// <summary>
    /// 项目全局线程管理类
    /// </summary>
    public class ModuleManager
    {
        private static ModuleManager moduleManager = new ModuleManager();

        private ModuleManager() { }

        /// <summary>
        /// 主页面
        /// </summary>
        private Form frmRunningOn { get; set; }

        /// <summary>
        /// 获得模块管理者对象（用于初始化）
        /// </summary>
        /// <param name="frmRunning"></param>
        /// <returns></returns>

        public static ModuleManager GetModuleManager(Form frmRunning)
        {
            moduleManager.frmRunningOn = frmRunning;
            return moduleManager;
        }

        /// <summary>
        /// 获得管理者对象（该方式用于已初始化的情况）
        /// </summary>
        /// <returns></returns>
        public static ModuleManager GetInstance()
        {
            if(null == moduleManager.frmRunningOn)                         // 未初始化的情况
            {
                return null;
            }

            return moduleManager;
        }

        /// <summary>
        /// 线程工厂方法
        /// </summary>
        private TaskManager taskManager = TaskManager.GetManager();

        /// <summary>
        /// 启动轮询
        /// </summary>
        public void Start()
        {
            // 系统数据初始化
            //taskManager.AddRunFunction(nameof(DoInitialization), DoInitialization);
            //taskManager.RunOverallFunction(nameof(DoInitialization));

            taskManager.AddRunFunction(nameof(ClearMemory), ClearMemory);
            taskManager.RunOverallFunction(nameof(ClearMemory));
        }

        /// <summary>
        /// 增加线程
        /// </summary>
        /// <param name="funcName"></param>
        /// <param name="arge"></param>
        public void AddRunFunction(string funcName, Action<object> arge)
        {
            taskManager.AddRunFunction(funcName, arge);
            taskManager.RunOverallFunction(funcName);

            LoggerHelper.Debug($"{funcName}线程增加成功！");
        }

        /// <summary>
        /// 关闭指定任务
        /// </summary>
        /// <param name="functionName"></param>
        public void Stop(ModuleType functionName)
        {
            switch (functionName)
            {
                case ModuleType.ClearMemory:
                    taskManager.CloseFunction(nameof(ClearMemory));
                    break;

                default:
                    break;
            }
        }

        /// <summary>
        /// 结束所有任务
        /// </summary>
        public void Stop()
        {
            taskManager.CloseFunction(nameof(ClearMemory));
            taskManager.CloseAll();
        }

        #region 系统数据初始化

        /// <summary>
        /// 系统初始化
        /// </summary>
        /// <param name="toke"></param>
        private void DoInitialization(object toke)
        {

        }

        #endregion

        #region 定期清理执行垃圾回收代码

        /// <summary>
        /// 清理内存时间间隔
        /// </summary>
        private int tmrClearMemoryInterval { get; } = 20 * 1000;               // 20秒回收一次

        /// <summary>
        /// 定期清理执行垃圾回收代码
        /// </summary>
        [DllImport("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize", ExactSpelling = true,
            CharSet = CharSet.Ansi, SetLastError = true)]
        private static extern int SetProcessWorkingSetSize(IntPtr process, int minimumWorkingSetSize,
            int maximumWorkingSetSize);

        /// <summary>
        /// 清理内存
        /// </summary>
        private void ClearMemory(object toke)
        {
            if (toke is CancellationToken)
            {
                var tok_source = (CancellationToken)toke;
                while (!tok_source.IsCancellationRequested)
                {
                    Thread.Sleep(tmrClearMemoryInterval);

                    GC.Collect();
                    GC.WaitForPendingFinalizers();

                    if (Environment.OSVersion.Platform == PlatformID.Win32NT)
                    {
                        SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1, -1);
                    }
                }
            }
        }

        #endregion
    }
}
